//给你一个 n x n 的二进制矩阵 grid 中，返回矩阵中最短 畅通路径 的长度。如果不存在这样的路径，返回 -1 。
//
// 二进制矩阵中的 畅通路径 是一条从 左上角 单元格（即，(0, 0)）到 右下角 单元格（即，(n - 1, n - 1)）的路径，该路径同时满足下述要求
//：
//
//
// 路径途经的所有单元格都的值都是 0 。
// 路径中所有相邻的单元格应当在 8 个方向之一 上连通（即，相邻两单元之间彼此不同且共享一条边或者一个角）。
//
//
// 畅通路径的长度 是该路径途经的单元格总数。
//
//
//
// 示例 1：
//
//
//输入：grid = [[0,1],[1,0]]
//输出：2
//
//
// 示例 2：
//
//
//输入：grid = [[0,0,0],[1,1,0],[1,1,0]]
//输出：4
//
//
// 示例 3：
//
//
//输入：grid = [[1,0,0],[1,1,0],[1,1,0]]
//输出：-1
//
//
//
//
// 提示：
//
//
// n == grid.length
// n == grid[i].length
// 1 <= n <= 100
// grid[i][j] 为 0 或 1
//
// Related Topics广度优先搜索 | 数组 | 矩阵
//
// 👍 220, 👎 0
//
//
//
//

package leetcode.editor.cn;

import java.util.LinkedList;
import java.util.Queue;

// 1091. 二进制矩阵中的最短路径
// https://leetcode.cn/problems/shortest-path-in-binary-matrix/?plan=graph&plan_progress=zylkshh
class ShortestPathInBinaryMatrix {
    public static void main(String[] args) {
        Solution solution = new ShortestPathInBinaryMatrix().new Solution();
        solution.shortestPathBinaryMatrix(new int[][]{{0, 1}, {1, 0}});
    }

    //leetcode submit region begin(Prohibit modification and deletion)
    class Solution {
        // DFS会超时
        // DFS是尝试一条一条的搜索，搜索全部之后才判断最短路径(不剪枝很容易超时)，BFS是全部一起搜索，如果有最短路径，那么不再搜索
        /*public int shortestPathBinaryMatrix(int[][] grid) {
            if (grid[0][0] == 1) return -1;
            this.m = grid.length;
            this.n = grid[0].length;
            this.res = Integer.MAX_VALUE;
            this.onPath = new boolean[m][n];
            dfs(grid, 0, 0, 1);
            return res == Integer.MAX_VALUE ? -1 : res;
        }

        boolean[][] onPath;
        int m, n, res;
        int[][] dirs = new int[][]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}};

        public void dfs(int[][] grid, int i, int j, int count) {
            if (i < 0 || j < 0 || i >= m || j >= n || grid[i][j] == 1 || onPath[i][j]) return;
            if (i == m - 1 && j == n - 1) {
                res = Math.min(res, count);
                return;
            }

            onPath[i][j] = true;
            for (int[] dir : dirs) {
                int x = i + dir[0];
                int y = j + dir[1];
                dfs(grid, x, y, count + 1);
            }
            // 需要回溯
            onPath[i][j] = false;
        }*/

        // BFS
        int[][] dirs = new int[][]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
        int m, n;
        boolean[][] visited;

        // https://leetcode.cn/problems/shortest-path-in-binary-matrix/solution/bfszui-duan-lu-jing-wen-ti-bfsdfsde-si-k-ngc5/
        public int shortestPathBinaryMatrix(int[][] grid) {
            if (grid[0][0] == 1) return -1;
            this.m = grid.length;
            this.n = grid[0].length;
            if (m == 1) return n; // [[0]]
            this.visited = new boolean[m][n];
            int res = 1;
            Queue<int[]> queue = new LinkedList<>();
            queue.offer(new int[]{0, 0});
            while (!queue.isEmpty()) {
                // 由于需要遍历所有的邻近位置，一层一层的去遍历，直到遍历到最后
                // 和310一个意思，和1162、417不一样
                int size = queue.size();
                for (int k = 0; k < size; k++) {
                    int[] poll = queue.poll();
                    int i = poll[0], j = poll[1];
                    for (int[] dir : dirs) {
                        int x = i + dir[0];
                        int y = j + dir[1];
                        if (x < 0 || y < 0 || x >= m || y >= n || grid[x][y] == 1 || visited[x][y]) continue;
                        if (x == m - 1 && y == n - 1) return res + 1;
                        queue.offer(new int[]{x, y});
                        visited[x][y] = true;
                    }

                }

                // 这一圈都加一
                res++;
            }

            return -1;
        }

    }
//leetcode submit region end(Prohibit modification and deletion)

}
